package com.ruoyi.web.controller.system.task;

import com.ruoyi.common.config.Global;
import com.ruoyi.common.config.RedisConfig;
import com.ruoyi.common.redis.RedisClientUtil;
import com.ruoyi.system.api.ResponseWithData;
import com.ruoyi.system.api.domain.Configuration;
import com.ruoyi.system.api.domain.ServiceNotice;
import com.ruoyi.system.api.domain.TaskPush;
import com.ruoyi.system.api.mapper.ConfigurationMapper;
import com.ruoyi.system.api.service.CcService;
import com.ruoyi.system.api.service.IServiceNoticeService;
import com.ruoyi.system.api.service.TaskService;
import com.ruoyi.system.api.service.impl.CcSyncDataServiceImpl;
import com.ruoyi.system.api.service.impl.TaskServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @ClassName MultithreadScheduleTask
 * @Description: TODO
 * @Author shihx
 * @Date 2020/3/27
 * @Version V1.0
 **/
// @Component注解用于对那些比较中立的类进行注释；
// 相对于在持久层、业务层和控制层分别采用 @Repository、@Service 和 @Controller 对分层中的类进行注释
@Component
// 1.开启定时任务
@EnableScheduling
// 2.开启多线程
@EnableAsync
public class MultithreadScheduleTask {

    @Autowired
    private CcService ccService;

    @Autowired
    private CcSyncDataServiceImpl ccSyncDataService;

    @Autowired
    private RedisConfig redisConfig;


    @Resource
    private ConfigurationMapper configurationMapper;

    @Autowired
    private TaskService taskService;

    /**
     * 配置文件
     */
    @Autowired
    private Global global;

    private static final Logger log = LoggerFactory.getLogger(MultithreadScheduleTask.class);

    //当前SyncTLServiceData方法是否正在运行
    private static boolean isRunSyncTLServiceData = false;

    //当前AutoMessagePush方法是否正在运行
    private static boolean isRunAutoMessagePush = false;

    /**
     * 2.2同步TL待指派服务信息接口
     *
     * @param
     * @methodName: syncTLServiceData
     * @description: TODO
     * @return: void
     * @author: shihx
     * @date: 2020-04-02 9:45
     **/
    @Async
    // 每5秒钟一次  同步
//    @Scheduled(cron = "0/5 * * * * ?")
    // 每1分钟一次
    @Scheduled(cron = "0 0/1 * * * ?")
    // 每天每1小时触发一次
//    @Scheduled(cron = "0 0 * * * ?")
    // 间隔1秒
//    @Scheduled(fixedDelay = 1000)
    public void syncTLServiceData() {
        log.info("======================================");
        log.info("syncTLServiceData Start...");

        try {
            String timerSwitch = global.getTimerSwitch();
            if (!"open".equals(timerSwitch)) {
                System.out.println("定时器（syncTLServiceData）以关闭" + new Date() + ", timerSwitch=" + timerSwitch);
                return;
            }

            // 判断当前日定时处理方法是否正在运行
            if (isRunSyncTLServiceData) {
                log.info("syncTLServiceData 正在执行，此方法不能重复执行，需要等待上次执行完再次执行！");
                return;
            } else {
                isRunSyncTLServiceData = true;
            }

            RedisClientUtil.getInstance()
                    .initialPool(redisConfig.getIp(), redisConfig.getPort(), redisConfig.getPassword(),
                            redisConfig.getTimeout());
            Jedis redis = RedisClientUtil.getInstance().getJedis();

            Long currTime = System.currentTimeMillis();
            if (StringUtils.isNotEmpty(redis.get("last_sync_time"))) {
                String syncTime = redis.get("last_sync_time");
                long lastSyncTime = Long.parseLong(syncTime);

                log.info("syncTLServiceData lastSyncTime:" + lastSyncTime);
                System.out.println("syncTLServiceData lastSyncTime:" + lastSyncTime);
                //ResponseWithData<?> syncResult = ccService.syncTLServiceData(lastSyncTime);
                ResponseWithData<?> syncResult = ccSyncDataService.syncServiceNotice(lastSyncTime);

                //数据同步处理成功，记录下次同步开始时间 否则不更新时间
                if (syncResult.getCode() == 200) {
                    redis.set("last_sync_time", String.valueOf(currTime));
                    log.info("update lastSyncTime:" + currTime);
                }
            } else {
                SimpleDateFormat simFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date dtBeg = simFormat.parse("2020-06-01 00:00:00");
                log.info("syncTLServiceData lastSyncTime:" + dtBeg);
                //ResponseWithData<?> syncResult = ccService.syncTLServiceData(dtBeg.getTime());
                ResponseWithData<?> syncResult = ccSyncDataService.syncServiceNotice(dtBeg.getTime());

                //数据同步处理成功，记录下次同步开始时间 否则不更新时间
                if (syncResult.getCode() == 200) {
                    redis.set("last_sync_time", String.valueOf(currTime));
                    log.info("update lastSyncTime:" + currTime);
                }
            }
            isRunSyncTLServiceData = false;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("syncTLServiceData 异常", e.getMessage());
            isRunSyncTLServiceData = false;
        } finally {
            log.info("syncTLServiceData End");
            log.info("======================================");
        }
    }


    /**
     * 自动消息提醒
     *
     * @param
     * @methodName: autoMessagePush
     * @description: TODO
     * @return: void
     * @author: wyl
     * @date: 2020-06-09 23:18
     **/
    @Async
    // 每1分钟一次
    @Scheduled(cron = "0 0/2 * * * ?")
    public void autoMessagePush() {
        try {
            String timerSwitch = global.getTimerSwitch();
            if (!"open".equals(timerSwitch)) {
                System.out.println("定时器（syncTLServiceData）以关闭" + new Date() + ", timerSwitch=" + timerSwitch);
                return;
            }

            // 判断当前日定时处理方法是否正在运行
            if (isRunAutoMessagePush) {
                log.info("autoMessagePush 正在执行，此方法不能重复执行，需要等待上次执行完再次执行！");
                return;
            } else {
                isRunAutoMessagePush = true;
            }

            try {
                //1、预计上门前1小时提醒工程师待上门服务
                waitingForTheDoor();
            } catch (Exception e) {
                log.error("waitingForTheDoor 异常", e.getMessage());
            }

            try {
                //2、待签到
                signIn();
            } catch (Exception e) {
                log.error("signIn 异常", e.getMessage());
            }

            try {
                //3、待签离 提醒
                signOff();
            } catch (Exception e) {
                log.error("signOff 异常", e.getMessage());
            }

            try {
                //4、待签离 开始时间 处理
                signOffStartTime();
            } catch (Exception e) {
                log.error("signOffStartTime 异常", e.getMessage());
            }

            try {
                //5、日志
                fillInLog();
            } catch (Exception e) {
                log.error("fillInLog 异常", e.getMessage());
            }

            try {
                //6、自动签离 推送提醒
                signOffAutoPush();
            } catch (Exception e) {
                log.error("signOffAutoPush 异常", e.getMessage());
            }

            try {
                //7、定时自动签离
                signOffAuto();
            } catch (Exception e) {
                log.error("signOffAuto 异常", e.getMessage());
            }

            isRunAutoMessagePush = false;
        } catch (Exception e) {
            log.error("autoMessagePush 异常", e.getMessage());
            isRunAutoMessagePush = false;
        }
    }

    /**
     * 待上门 定时推送
     *
     * @param
     * @methodName: waitingForTheDoor
     * @description: TODO
     * @return: void
     * @author: shihx
     * @date: 2020-04-02 10:03
     **/
    @Async
    // 每1分钟一次
    //1、预计上门前1小时提醒工程师待上门服务
    //@Scheduled(cron = "0 0/1 * * * ?")
    public void waitingForTheDoor() {

        String timerSwitch = global.getTimerSwitch();
        if (!"open".equals(timerSwitch)) {
            System.out.println("定时器（waitingForTheDoor）以关闭" + new Date());
            return;
        }

        Configuration configuration = new Configuration();
        configuration.setName("serve_advance_tips_time");
        List<Configuration> configurations = configurationMapper.selectConfigurationList(configuration);
        if (configurations != null && configurations.size() > 0) {
            if (StringUtils.isNotEmpty(configurations.get(0).getValue())) {
                TaskPush taskPush = new TaskPush();
                //设置应该提醒的时间，当前时间——
                taskPush.setSearchTime(this.addHour(new Date(), Long.parseLong(configurations.get(0).getValue())));
                taskService.waitingForTheDoor(taskPush, configurations.get(0).getValue());
            }
        }
    }

    /**
     * 2、待签到
     *
     * @param
     * @methodName: signIn
     * @description: TODO
     * @return: void
     * @author: shihx
     * @date: 2020-04-02 10:05
     **/
    @Async
    // 每1分钟一次
    //@Scheduled(cron = "0 0/1 * * * ?")
    public void signIn() {

        String timerSwitch = global.getTimerSwitch();
        if (!"open".equals(timerSwitch)) {
            System.out.println("定时器（signIn）以关闭" + new Date());
            return;
        }

        Date date = new Date();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 待签到分两种情况
        // 1、如果到预计上门时间该客户还未签到操作，系统可提示其签到。
        TaskPush taskPush1 = new TaskPush();
        taskPush1.setSearchTime(sdf.format(date));
        taskService.signIn1(taskPush1);


        // 2、预计上门时间n分钟后距离当日计划服务客户n公里内提示是否签到。
        List<Configuration> configurations = configurationMapper.selectConfigurationList(null);
        // 预计上门时间n分钟后提示是否签到
        String serveStartTipsTime = "";
        // 预计上门时间距离计划服务客户n公里内提示是否签到
        String serveStartTipsDistance = "";
        if (configurations != null && configurations.size() > 0) {
            for (int i = 0; i < configurations.size(); i++) {
                if ("serve_start_tips_time".equals(configurations.get(i).getName())) {
                    serveStartTipsTime = configurations.get(i).getValue();
                    continue;
                }
                if ("serve_start_tips_distance".equals(configurations.get(i).getName())) {
                    serveStartTipsDistance = configurations.get(i).getValue();
                    continue;
                }
            }

            TaskPush taskPush2 = new TaskPush();
            taskPush2.setSearchTime(this.addMinute(date, Long.parseLong(serveStartTipsTime)));
            taskPush2.setDistance(serveStartTipsDistance);
            taskService.signIn2(taskPush2);

        }
    }

//    /**
//     * 待签离 提醒
//     * @methodName: signOff
//     * @description: TODO
//     * @param
//     * @return: void
//     * @author: shihx
//     * @date: 2020-04-02 10:05
//    **/
//    @Async
//    // 每1分钟一次
//    @Scheduled(cron = "0 0/1 * * * ?")
//    public void signOff(){
//
//        String timerSwitch = global.getTimerSwitch();
//        if(!"open".equals(timerSwitch)){
//            System.out.println("定时器（signOff）以关闭"+new Date());
//            return;
//        }
//
//        Date date = new Date();
//
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        // 待签离分两种情况
//        // 1、根据预计离开时间，提醒工程师签离。
//        TaskPush taskPush1 = new TaskPush();
//        taskPush1.setSearchTime(sdf.format(date));
//        taskService.signOff1(taskPush1);
//
//
//        // 2、离开签到客户n公里范围外n分钟，提示签离。
//        List<Configuration> configurations = configurationMapper.selectConfigurationList(null);
//        // 离开签到客户n小时，提示签离
//        // 2020-05-29日 把N小时 改为 N分钟
//        String serve_end_tips_time = "";
//        // 离开签到客户n公里范围内，提示签离
//     //   String serve_end_tips_distance = "";
//        if(configurations!=null && configurations.size()>0) {
//            for (int i = 0; i < configurations.size(); i++) {
//                if ("serve_end_tips_time".equals(configurations.get(i).getName())) {
//                    serve_end_tips_time = configurations.get(i).getValue();
//                    continue;
//                }
////                if ("serve_end_tips_distance".equals(configurations.get(i).getName())) {
////                    serve_end_tips_distance = configurations.get(i).getValue();
////                    continue;
////                }
//            }
//
//            TaskPush taskPush2 = new TaskPush();
//            taskPush2.setSearchTime(this.addMinute(date, Long.parseLong(serve_end_tips_time)));
//          //  taskPush2.setDistance(serve_end_tips_distance);
//            taskService.signOff2(taskPush2, serve_end_tips_time);
//        }
//    }


    /**
     * 3、待签离 提醒
     *
     * @param
     * @methodName: signOff
     * @description: TODO
     * @return: void
     * @author: 2020-6-8 日 签离提醒
     * @date: 2020-04-02 10:05
     **/
    @Async
    // 每1分钟一次
    //@Scheduled(cron = "0 0/6 * * * ?")
    public void signOff() {

        String timerSwitch = global.getTimerSwitch();
        if (!"open".equals(timerSwitch)) {
            System.out.println("定时器（signOff）以关闭" + new Date());
            return;
        }

        Date date = new Date();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 待签离分两种情况
        // 1、根据预计离开时间，提醒工程师签离。
        TaskPush taskPush1 = new TaskPush();
        taskPush1.setSearchTime(sdf.format(date));
        taskService.signOff1(taskPush1);


        // 2、离开签到客户n公里范围外n分钟，提示签离。
        TaskPush taskPush2 = new TaskPush();
        taskPush2.setSearchTime(sdf.format(date));
        taskService.signOff3(taskPush2);


    }


    /**
     * 4、待签离 开始时间 处理
     *
     * @param
     * @methodName: signOff
     * @description: TODO
     * @return: void
     * @author: shihx
     * @date: 2020-04-02 10:05
     **/
    @Async
    // 每1分钟一次
    //@Scheduled(cron = "0 0/6 * * * ?")
    public void signOffStartTime() {

        String timerSwitch = global.getTimerSwitch();
        if (!"open".equals(timerSwitch)) {
            System.out.println("定时器（signOff）以关闭" + new Date());
            return;
        }

        // 2、离开签到客户n公里范围外n分钟，提示签离。
        List<Configuration> configurations = configurationMapper.selectConfigurationList(null);
        String serve_end_tips_time = "";
        // 离开签到客户n公里范围内，提示签离
        String serve_end_tips_distance = "";
        if (configurations != null && configurations.size() > 0) {
            for (int i = 0; i < configurations.size(); i++) {
                if ("serve_end_tips_distance".equals(configurations.get(i).getName())) {
                    serve_end_tips_distance = configurations.get(i).getValue();
                    continue;
                }
                if ("serve_end_tips_time".equals(configurations.get(i).getName())) {
                    serve_end_tips_time = configurations.get(i).getValue();
                    continue;
                }
            }

            TaskPush taskPush2 = new TaskPush();
            taskPush2.setDistance(serve_end_tips_distance);
            taskService.signOffStartTime(taskPush2, serve_end_tips_time);
        }
    }

    /**
     * 5、日志
     *
     * @param
     * @methodName: fillInLog
     * @description: TODO
     * @return: void
     * @author: shihx
     * @date: 2020-04-02 10:06
     **/
    @Async
    // 每1分钟一次
    //@Scheduled(cron = "0 0/6 * * * ?")
    public void fillInLog() {

        String timerSwitch = global.getTimerSwitch();
        if (!"open".equals(timerSwitch)) {
            System.out.println("定时器（fillInLog）以关闭" + new Date());
            return;
        }

        Configuration configuration = new Configuration();
        configuration.setName("fill_log__tips_time");
        List<Configuration> configurations = configurationMapper.selectConfigurationList(configuration);
        if (configurations != null && configurations.size() > 0) {
            if (StringUtils.isNotEmpty(configurations.get(0).getValue())) {
                TaskPush push = new TaskPush();
                push.setState("3");
                push.setFillInLogPush("0");
                push.setSearchTime(this.reduceHour(new Date(), Long.parseLong(configurations.get(0).getValue())));
                taskService.fillInLog(push);
            }
        }
    }


    /**
     * 6、自动签离 推送提醒
     *
     * @param
     * @methodName: signOffAuto
     * @description: TODO
     * @return: void
     * @author: shihx
     * @date: 2020-04-02 10:06
     **/
    @Async
    // 每1分钟一次
    //@Scheduled(cron = "0 0/1 * * * ?")
    public void signOffAutoPush() {

        String timerSwitch = global.getTimerSwitch();
        if (!"open".equals(timerSwitch)) {
            System.out.println("定时器（signOffAutoPush）以关闭" + new Date());
            return;
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<Configuration> configurations = configurationMapper.selectConfigurationList(null);
        // 离开签到客户n公里范围外且超过预计结束时间，提示系统将自动签离
        String auto_serve_end_tips_distance = "";
        if (configurations != null && configurations.size() > 0) {
            for (int i = 0; i < configurations.size(); i++) {
                if ("auto_serve_end_tips_distance".equals(configurations.get(i).getName())) {
                    auto_serve_end_tips_distance = configurations.get(i).getValue();
                    continue;
                }
            }
            TaskPush taskPush2 = new TaskPush();
            taskPush2.setState("2");
            taskPush2.setSignOffAutoPush("0");
            taskPush2.setSearchTime(sdf.format(new Date()));
            taskPush2.setDistance(auto_serve_end_tips_distance);
            taskService.signOffAutoPush(taskPush2);
        }
    }

    /**
     * 7、定时自动签离
     *
     * @param
     * @methodName: signOffAuto
     * @description: TODO
     * @return: void
     * @author: shihx
     * @date: 2020-04-07 11:25
     **/
    @Async
    // 每1分钟一次
    //@Scheduled(cron = "0 0/6 * * * ?")
    public void signOffAuto() {

        String timerSwitch = global.getTimerSwitch();
        if (!"open".equals(timerSwitch)) {
            System.out.println("定时器（signOffAuto）以关闭" + new Date());
            return;
        }
        // 离开签到客户n公里范围外且超过预计结束时间，提示系统将自动签离
        String auto_serve_end_tips_distance = "";
        Configuration configuration = new Configuration();
        List<Configuration> configurations = configurationMapper.selectConfigurationList(configuration);
        if (configurations != null && configurations.size() > 0) {
            for (int i = 0; i < configurations.size(); i++) {
                if ("auto_serve_end_tips_distance".equals(configurations.get(i).getName())) {
                    auto_serve_end_tips_distance = configurations.get(i).getValue();
                    continue;
                }
            }
            TaskPush push = new TaskPush();
            push.setState("2");
            push.setSignOffAutoPush("1");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            push.setSearchTime(sdf.format(new Date()));
            push.setDistance(auto_serve_end_tips_distance);
            taskService.signOffAuto(push);
        }
    }


    /**
     * 获取指定日期day天后的日期
     *
     * @param date
     * @param day
     * @methodName: addDate
     * @description: TODO
     * @return: java.util.Date
     * @author: shihx
     * @date: 2020-04-02 10:54
     **/
    public String addDate(Date date, long day) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long time = date.getTime(); // 得到指定日期的毫秒数
        day = day * 24 * 60 * 60 * 1000; // 要加上day的天数转换成毫秒数
        time += day; // 相加得到新的毫秒数
        return sdf.format(new Date(time)); // 将毫秒数转换成日期
    }

    /**
     * 获取指定日期hour小时后的日期
     *
     * @param date
     * @param hour
     * @methodName: addHour
     * @description: TODO
     * @return: java.util.Date
     * @author: shihx
     * @date: 2020-04-02 10:54
     **/
    public String addHour(Date date, long hour) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long time = date.getTime(); // 得到指定日期的毫秒数
        hour = hour * 60 * 60 * 1000; // 要加上hour的小时数转换成毫秒数
        time += hour; // 相加得到新的毫秒数
        return sdf.format(new Date(time)); // 将毫秒数转换成日期
    }

    public String addMinute(Date date, long minute) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long time = date.getTime(); // 得到指定日期的毫秒数
        minute = minute * 60 * 1000; // 要加上hour的小时数转换成毫秒数
        time += minute; // 相加得到新的毫秒数
        return sdf.format(new Date(time)); // 将毫秒数转换成日期
    }

    public String reduceMinute(Date date, long minute) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long time = date.getTime(); // 得到指定日期的毫秒数
        minute = minute * 60 * 1000; // 要加上hour的小时数转换成毫秒数
        time -= minute; // 相减得到新的毫秒数
        return sdf.format(new Date(time)); // 将毫秒数转换成日期
    }

    public String reduceHour(Date date, long hour) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        long time = date.getTime(); // 得到指定日期的毫秒数
        hour = hour * 60 * 60 * 1000; // 要加上hour的小时数转换成毫秒数
        time -= hour; // 相加得到新的毫秒数
        return sdf.format(new Date(time)); // 将毫秒数转换成日期
    }


}
